#include "nrf24l01.h"

nRF24L01::nRF24L01()
{
    mCE = 22;
    mCSN = 24;
    mSCK = 26;
    mMOSI = 28;
    mMISO = 30;
    mIRQ = 32;

    txPayload = 32;
    addrWidth = 5;
}

uint8_t nRF24L01::writeData(uint8_t data)
{
    uint8_t i;
    for(i = 0 ; i < 8 ; i++)
    {
        if(data & 0x80)
        {
            digitalWrite(mMOSI, 1);
        }
        else
        {
            digitalWrite(mMOSI, 0);
        }
        digitalWrite(mSCK, 1);
        data <<= 1;
        if(digitalRead(mMISO) == 1)
        {
            data |= 1;
        }
        digitalWrite(mSCK, 0);
    }
 
    return(data);
}


uint8_t nRF24L01::writeValueToRegister(uint8_t regAddr, uint8_t value)
{
    uint8_t status;

    csnLow();
    status = writeData(regAddr);
    writeData(value);
    csnHigh();
    return(status);
}

uint8_t nRF24L01::readValueFromRegister(uint8_t regAddr)
{
    csnLow();
    writeData(regAddr);
    uint8_t status = writeData(0);
    csnHigh();

    return(status);
}

uint8_t nRF24L01::writeBuffToRegister(uint8_t regAddr,uint8_t buff[], uint8_t len)
{
    uint8_t status,i;

    csnLow();
    status = writeData(regAddr);
    for(i = 0 ; i < len; i++)
    {
        writeData(*buff++);
    }
    csnHigh();
    return(status);
}

uint8_t nRF24L01::readBuffFromRegister(uint8_t regAddr, uint8_t buff[], uint8_t len)
{
    uint8_t status ,i;

    csnLow();
    status = writeData(regAddr);
    for (i = 0 ; i < len ; i++)
    {
        buff[i] = writeData(0);
    }
    csnHigh();
    return status;
}

void nRF24L01::standBy_Two()
{
    uint8_t status = readValueFromRegister( CONFIG);
    writeValueToRegister(WRITE_REG+CONFIG,status & PWR_UP );
    ceHigh();
}

void nRF24L01::standBy_One()
{
    uint8_t status = readValueFromRegister( CONFIG);
    writeValueToRegister(WRITE_REG+CONFIG,status | PWR_UP );
    ceLow();
}

void nRF24L01::flushAll()
{
    //writeValueToRegister(WRITE_REG + FLUSH_TX,0);
    //writeValueToRegister(WRITE_REG + FLUSH_RX,0);
    writeData(FLUSH_TX);
    writeData(FLUSH_RX);
}

//----------------------------------------
void nRF24L01::ceHigh()
{
    digitalWrite(mCE,HIGH);
}

void nRF24L01::ceLow()
{
    digitalWrite(mCE,LOW);
}

void nRF24L01::csnHigh()
{
    digitalWrite(mCSN,HIGH);
}

void nRF24L01::csnLow()
{
    digitalWrite(mCSN,LOW);
}
void nRF24L01::initPins()
{
    pinMode(mCE,  OUTPUT);
    pinMode(mCSN, OUTPUT);
    pinMode(mMOSI,  OUTPUT);
    pinMode(mMISO, INPUT);
    pinMode(mIRQ, INPUT);
    pinMode(mSCK, OUTPUT);
    
    digitalWrite(mIRQ, 0);
    digitalWrite(mCE, 0);      
    digitalWrite(mCSN, 1);               
}
void nRF24L01::applyRFSettings(uint8_t localAddr[])
{
    ceLow();
    writeBuffToRegister(WRITE_REG+TX_ADDR,localAddr,addrWidth);
    writeBuffToRegister(WRITE_REG+RX_ADDR_P0,localAddr,addrWidth);

    writeValueToRegister(WRITE_REG+EN_AA,0xff);
    writeValueToRegister(WRITE_REG+EN_RXADDR,0x01);
    writeValueToRegister(WRITE_REG+SETUP_RETR,0x1a);
    
    writeValueToRegister(WRITE_REG + RX_PW_P0, txPayload); 
    //
    writeValueToRegister(WRITE_REG+RF_CH,40);
    writeValueToRegister(WRITE_REG+RF_SETUP,0x07);
    
}

uint8_t nRF24L01::Tx_Packages(uint8_t data[])
{
  ceLow ();  
  writeBuffToRegister(WR_TX_PLOAD,data,txPayload);
  writeValueToRegister(WRITE_REG+CONFIG,0x0E);
  ceHigh ();
}
void nRF24L01::Rx_Modestart()
{
    ceLow();
    writeValueToRegister(WRITE_REG + CONFIG, 0x0f);   
    ceHigh();
}

uint8_t nRF24L01::startRecvData(uint8_t *data)
{
    Rx_Modestart();
    uint8_t status = 0;

    uint8_t time = 0;
    //200 ms超时，可自行修改
    do {
        time = time + 1;
        delay(5);
        status = readValueFromRegister( STATUS);

        status = status & RX_DR;
    }while ((status != 0) && (time <= 40));

    if (status == 0x40)
    {
        readBuffFromRegister(RD_RX_PLOAD, data, txPayload);
        return 1;
    }
    else
        return 0;
}
uint8_t nRF24L01::checkACK()
{
   uint8_t sta = readValueFromRegister ( STATUS );
  if((sta & TX_DS))
  {
    writeValueToRegister (WRITE_REG + STATUS,0xff);
    ceLow();
    csnLow();
    writeData( FLUSH_TX );
    csnHigh ();
    return 1;
  }
  else if (sta & MAX_RT)
  {
    writeValueToRegister (WRITE_REG + STATUS,0xff);
    ceLow();
    csnLow();
    writeData( FLUSH_TX );
    csnHigh ();
    return 2;
  }
  else
    return 0;
}
